﻿// -----------------------------------------------------------------------
// <copyright file="CharacterFactory.cs" company="Diddly Squad">
// </copyright>
// -----------------------------------------------------------------------
using FarseerPhysics.Dynamics;
using FarseerPhysics.Factories;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Audio;

namespace DiddlySquat
{
	/// <summary>
	/// Class to create characters with factory pattern
	/// </summary>
	public class CharacterFactory
	{
		private readonly ContentManager content;

		private readonly World world;


		/// <summary>
		/// Initializes a new instance of the <see cref="CharacterFactory"/> class.
		/// </summary>
		/// <param name="contentManager">The content manager.</param>
		/// <param name="world">The world.</param>
		public CharacterFactory(ContentManager contentManager, World world)
		{
			this.content = contentManager;
			this.world = world;
		}

		/// <summary>
		/// Creates the player.
		/// </summary>
		/// <param name="position">The position.</param>
		/// <param name="health">The health.</param>
		/// <returns>New Player</returns>
		public Player CreatePlayer(Vector2 position, double health=Constants.PlayerStartingHealth)
		{
			Player player = new Player();
			
			// Load sprites
			var playerSprite = this.content.Load<Texture2D>(Constants.PlayerSprite);
			var deathSprite = this.content.Load<Texture2D>(Constants.PlayerDeathSprite);
            var exitSprite = this.content.Load<Texture2D>(Constants.PlayerExitSprite);

			var body = this.CreateBody(
				Constants.PlayerSizeFactor, position, Constants.PlayerRestitution, Constants.PlayerFriction, player);

			body.CollisionCategories = Constants.PlayerCollisionCategory;
			body.CollidesWith = Constants.PlayerCollidesWith;

			var weapon = new BasicGun();
			var weaponTex = this.content.Load<Texture2D>("weapon1");
			var projectileTex = this.content.Load<Texture2D>("bullet");
			var shootingSound = this.content.Load<SoundEffect>("sound/shoot");
			weapon.Initialize(world, position, weaponTex, projectileTex, shootingSound);

			player.Initialize(this.world, position, body, playerSprite, health, weapon, deathSprite, exitSprite);

			return player;
		}

		/// <summary>
		/// Creates the enemy.
		/// </summary>
		/// <param name="position">The position.</param>
		/// <param name="enemyType">Type of the enemy.</param>
		/// <param name="health">The health.</param>
		/// <returns>New Enemy</returns>
		public Enemy CreateEnemy(Vector2 position, Enums.EnemyType enemyType, double health=Constants.DefaultEnemyHealth)
		{
			Enemy enemy;

			switch (enemyType)
			{
				case Enums.EnemyType.BigBoy:
					enemy = new BigBoy();
					break;
				case Enums.EnemyType.SmallIdiot:
					enemy = new SmallIdiot();
					break;
				case Enums.EnemyType.Oldie:
					enemy = new Oldie();
					break;
				case Enums.EnemyType.Flyer:
					enemy = new Flyer();
					break;
				default:
					enemy = new Oldie();
					enemy.InitializeSpeedMaxSpeedRange(Constants.DefaultEnemySpeed, Constants.DefaultEnemyMaxSpeed, Constants.DefaultEnemyRange);
					break;
			}
			var body = this.CreateBody(enemy.SizeFactor, position, enemy.EnemyRestitution, enemy.EnemyFriction, enemy);

			var enemySprite = this.content.Load<Texture2D>(enemy.EnemySprite);
			var deathSprite = this.content.Load<Texture2D>(Constants.EnemyDeathSprite);

			body.CollisionCategories = Constants.EnemyCollisionCategory;
			body.CollidesWith = Constants.EnemyCollidesWith;

			enemy.Initialize(this.world, position, body, enemySprite, health, deathSprite);
			
			return enemy;
		}

		/// <summary>
		/// Creates the body.
		/// </summary>
		/// <param name="sizeFactor">The size factor.</param>
		/// <param name="position">The position.</param>
		/// <param name="restitution">The restitution.</param>
		/// <param name="friction">The friction.</param>
		/// <param name="me">Character who's body is created</param>
		/// <returns>Body in the world.</returns>
		private Body CreateBody(float sizeFactor, Vector2 position, float restitution, float friction, Character me)
		{
			Body body = BodyFactory.CreateCircle(
				world, (sizeFactor) * Constants.DefaultCharacterSize, 1f, position, me);
			body.BodyType = BodyType.Dynamic;

			body.Restitution = restitution;
			body.Friction = friction;

			return body;
		}
	}
}
